package com.modules.bluetooth;//指示这个类的包所属

import android.widget.Toast;//用来打印
//蓝牙适配器
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;

//导入react封装需要的库
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
//用来得到从javascript得到的array的
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.IllegalViewOperationException;

//导入promise包
import com.facebook.react.bridge.Promise;
//为了让callback可以返回数组
import com.facebook.react.bridge.WritableArray;//接口
import com.facebook.react.bridge.WritableNativeArray;//实现

//导入java要用的工具
import java.util.HashMap;
import java.util.Map;

import java.util.Set;
import java.util.Iterator;

import java.util.UUID;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;

public class BluetoothModule extends ReactContextBaseJavaModule {

	//取得默认的蓝牙适配器 //调用方法获取蓝牙适配器
	private BluetoothAdapter _mybluetooth= BluetoothAdapter.getDefaultAdapter();
	private BluetoothSocket _socket = null;
    private Set<BluetoothDevice> _devices=null;//与之配对的蓝牙设备列表
    private BluetoothDevice _remotedev=null;//要操作的配对蓝牙设备
    private OutputStream _myOutputStream=null;//写通道
    private InputStream _myInputStream=null;//读通道
    private String _inputbytes = "";//读数据的缓存
    private boolean _bReadThreadIsRun = false;//标记位，代表接收数据的线程是否在运行
    private boolean _bReadThreadStartRun = false;//标记位，代表是否要暂停还是继续运行线程

	//构造函数
	public BluetoothModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }
    //在javascript中的命名
    @Override
    public String getName() {
        return "BluetoothAndroid";
    }

    //暴露到react的方法，打开蓝牙适配器
    @ReactMethod
    public void enable() {
    	_mybluetooth.enable();
    	//toast显示信息
        Toast.makeText(getReactApplicationContext(),"open bluetooth", Toast.LENGTH_SHORT).show();
    }

    //暴露到react的方法，关闭蓝牙适配器
    @ReactMethod
    public void disable() {
    	_mybluetooth.disable();
    	//toast显示信息
        Toast.makeText(getReactApplicationContext(),"disable bluetooth", Toast.LENGTH_SHORT).show();
    }

/*
    @ReactMethod
    public void startDiscovery() {
    	_mybluetooth.startDiscovery();
    	//toast显示信息
        Toast.makeText(getReactApplicationContext(),"disable bluetooth", Toast.LENGTH_SHORT).show();
    }*/

    //得到所有已经配对的蓝牙设备
    @ReactMethod
    public void getBondedDevices() {
    	_devices = _mybluetooth.getBondedDevices();//set集合
    	if(_devices.size()>0){
    		//使用迭代器遍历
    		for(Iterator iterator = _devices.iterator();iterator.hasNext();){
    			_remotedev=(BluetoothDevice)iterator.next();
    		};  		
    	};
    }

    //socket连接这种情况是远端设备作为server
    //运行前提：1.蓝牙已经打开并配对
    //		   2._remotedev不为空，函数getBondedDevices会对其赋值
    //         3.远端设备开启了server服务
    //做的事情：1.进行socket连接
    //		  2.对io读写端口_myOutputStream进行赋值
    @ReactMethod
    public void socketconnet() {
    	//这个uuid比较通用
    	final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    	UUID uuid = UUID.fromString(SPP_UUID);
    	if(_remotedev==null){
            Toast.makeText(getReactApplicationContext(),"空设备", Toast.LENGTH_SHORT).show();
            return;
    	}
    	//创建socket
		try{
            //_socket = _remotedev.createInsecureRfcommSocketToServiceRecord(uuid);
			_socket = _remotedev.createRfcommSocketToServiceRecord(uuid);
			//如果没有连接
			if(!_socket.isConnected()){
				//连接
				_socket.connect(); 
			}
			//对写通道进行赋值
			try{
				_myOutputStream = _socket.getOutputStream();
			}catch(IOException e){
				Toast.makeText(getReactApplicationContext(),"1--"+e.toString(), Toast.LENGTH_SHORT).show();
			}

            //对读读通道进行赋值
            try{
                _myInputStream = _socket.getInputStream();

            }catch(IOException e){
                Toast.makeText(getReactApplicationContext(),"2--"+e.toString(), Toast.LENGTH_SHORT).show();
            }
            // //如果接收数据的线程还没启动，那么就启动
            // if(_bReadThreadIsRun==false){
            //     ReadThread.start();
            //     _bReadThreadIsRun=true;
            // }else{
            //     _bReadThreadStartRun=true;//如果线程已经启动了，那么就让其从暂停状态变为运行状态
            // }

		}catch(IOException e){
			//toast显示信息
			Toast.makeText(getReactApplicationContext(),"3--"+_remotedev+e.toString(), Toast.LENGTH_SHORT).show();
		}finally{

		}
    }
    //关闭socket连接
    @ReactMethod
    public void socketclose() {
    	if (_socket != null) {
			try {
				Toast.makeText(getReactApplicationContext(),"socket close", Toast.LENGTH_SHORT).show();
				_socket.close();
                _socket=null;
			} catch (IOException e) {

			}
		}
	}
    //socket发送数据,前提是已经进行了socket链接
    @ReactMethod
    public void socketwrite(ReadableArray arry) {
    	byte[] sendbytes=new byte[arry.size()];
    	for(int i=0;i<arry.size();i++){
    		sendbytes[i]=(byte) arry.getInt(i);
    	}

    	Toast.makeText(getReactApplicationContext(),"socket write", Toast.LENGTH_SHORT).show();
    	try{
    		//_myOutputStream.write(0xfe);
    		_myOutputStream.write(sendbytes);
    	}catch(IOException e){
			//toast显示信息
			Toast.makeText(getReactApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
    	}
    }

    /*请求socket发送数据，发送后等待6秒，等待对方发送指定的回复字符过来，返回一个promise给javascript
        输入：arrysendbytes javascript发过来需要发送的数组串
               wantreturn   想接收到的数组串
        返回：promise
        前提：蓝牙打开，已经适配，与适配设备已经建立socket链接
        用回调函数的方式将返回值提供给javascript
    */
    @ReactMethod
    public void socketwriteReCallback(
        ReadableArray arrysendbytes,
        Integer wantRXnum,
        Callback errorCallback,
        Callback successCallback
    ){
        String s="";
        int num=0;
        int rxnum=0;
        byte[] buffer = new byte[1024];
        WritableArray mywritableArray = new WritableNativeArray();;//为了callback可以返回数组
        socketwrite(arrysendbytes);
        try{
            while(rxnum<wantRXnum){//如果还没接收到需要接收的个数就一直接收
                //放到while循环中可以读出所有数据。
                //读入数据,这一句起始会柱塞整个线程，不过注意这条命令只会读出一个字符
                num = _myInputStream.read(buffer);//统计一共接收了多少个字节
                rxnum = rxnum+num;//接收的字节数加1  
                //String s0 = new String(buffer,0,num);
                //s=s+s0;
                //将接收到的字节加入
                for(int i=0;i<num;i++){
                    mywritableArray.pushInt((int)buffer[i]);
                }
                //if(_myInputStream.available()==0)break;  //短时间没有数据才跳出循环
            }
            //Toast.makeText(getReactApplicationContext(),s, Toast.LENGTH_SHORT).show();
            //成功返回将返回的数组用回调函数的方式返回给javascript
            successCallback.invoke(mywritableArray);
        }catch(IOException e){
            Toast.makeText(getReactApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
            //将错误用回调函数的方式传给javascript
            errorCallback.invoke(e.getMessage());
        }
    }


}